﻿// Copyright (c) 2012 - 2020 Jared Zheng <jaredz at outlook dot com>
// Buddha Framework is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
//          http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.
//
// Create : 2012-12-01 version 0.1 Jared Zheng <jaredz at outlook dot com>
// Update : 2018-12-05 version 3.1.5 Jared Zheng <jaredz at outlook dot com>

#include "stdafx.h"
#include "resource.h"
#include "network.h"
#include "servermap.h"
#include "ServerLoader.h"

///////////////////////////////////////////////////////////////////////////////////////////////////////////
// CCommonDlg
UInt CCommonDlg::OnHandle(Int nEvent, uintptr_t utData, ULLong ullParam)
{
    switch (nEvent)
    {
    case PAKE_LIVE:
        {
            OnLive(utData != false);
        }
        break;
    case PAKE_LINK:
        {
            OnLink((Int)ullParam, utData);
        }
        break;
    case PAKE_UPDATE:
        {
            OnUpdate((Int)ullParam, utData);
        }
        break;
    case PAKE_SYNC:
        {
            OnSync((Int)ullParam, utData);
        }
        break;
    case PAKE_UNLINK:
        {
            OnUnlink((Int)ullParam, utData);
        }
        break;
    case PAKT_CENTER:
    case PAKT_BALANCE:
    case PAKT_AUTHORDB:
    case PAKT_AUTHOR:
    case PAKT_MASTERDB:
    case PAKT_MASTER:
    case PAKT_SERVICE:
    case PAKT_GATE:
        {
            SetServer(reinterpret_cast<ICommonServer*>(utData));
        }
        break;
    default:
        {
        }
    }
    return RET_OKAY;
}

UInt CCommonDlg::OnHandle(Int, CEventBase&, ULLong)
{
    return RET_OKAY;
}

UInt CCommonDlg::OnHandle(Int nEvent, CStream& Stream, ULLong ullParam)
{
    if (nEvent == PAKE_SYNC)
    {
        OnSync((Int)ullParam, Stream);
    }
    return RET_OKAY;
}

UInt CCommonDlg::OnHandle(Int, UInt)
{
    assert(m_pServer != nullptr);
    if (m_pServer->Update() == RET_OKAY)
    {
        UpdateServerInfo();
    }
    return RET_OKAY;
}

void CCommonDlg::InitServerData(Int nServerIndex)
{
    CXListView* pListView = GetListView(nServerIndex);
    if (pListView != nullptr)
    {
        pListView->SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
        Int nIndex = 0;
        if (nServerIndex < PAKT_MAX)
        {
            nIndex = InitServerCommonData(nServerIndex);
        }

        CStringFix strTemp;
        switch (nServerIndex)
        {
        case PAKT_BALANCE:
            {
                strTemp.Load(IDS_UDP_EXTERNAL);
                pListView->AddColumn(*strTemp, nIndex, 150, -1, LVCF_WIDTH | LVCF_TEXT);
            }
            break;
        case PAKT_AUTHORDB:
            {
                strTemp.Load(IDS_LISTEN_INTERNAL);
                pListView->AddColumn(*strTemp, nIndex, 150, -1, LVCF_WIDTH | LVCF_TEXT);
            }
            break;
        case PAKT_AUTHOR:
            {
                strTemp.Load(IDS_TCP_EXTERNAL);
                pListView->AddColumn(*strTemp, nIndex, 150, -1, LVCF_WIDTH | LVCF_TEXT);
                ++nIndex;

                strTemp.Load(IDS_UDP_TO_MASTER);
                pListView->AddColumn(*strTemp, nIndex, 150, -1, LVCF_WIDTH | LVCF_TEXT);
                ++nIndex;

                strTemp.Load(IDD_AUTHORDB);
                pListView->AddColumn(*strTemp, nIndex, 150, -1, LVCF_WIDTH | LVCF_TEXT);
            }
            break;
        case PAKT_MASTERDB:
            {
                strTemp.Load(IDS_LISTEN_INTERNAL);
                pListView->AddColumn(*strTemp, nIndex, 150, -1, LVCF_WIDTH | LVCF_TEXT);
            }
            break;
        case PAKT_MASTER:
            {
                strTemp.Load(IDS_LISTEN_INTERNAL);
                pListView->AddColumn(*strTemp, nIndex, 150, -1, LVCF_WIDTH | LVCF_TEXT);
                ++nIndex;

                strTemp.Load(IDS_UDP_TO_AUTHOR);
                pListView->AddColumn(*strTemp, nIndex, 150, -1, LVCF_WIDTH | LVCF_TEXT);
                ++nIndex;

                strTemp.Load(IDD_MASTERDB);
                pListView->AddColumn(*strTemp, nIndex, 150, -1, LVCF_WIDTH | LVCF_TEXT);
            }
            break;
        case PAKT_SERVICE:
            {
                strTemp.Load(IDD_MASTER);
                pListView->AddColumn(*strTemp, nIndex, 150, -1, LVCF_WIDTH | LVCF_TEXT);
                ++nIndex;

                strTemp.Load(IDD_MASTERDB);
                pListView->AddColumn(*strTemp, nIndex, 150, -1, LVCF_WIDTH | LVCF_TEXT);
            }
            break;
        case PAKT_GATE:
            {
                strTemp.Load(IDS_TCP_EXTERNAL);
                pListView->AddColumn(*strTemp, nIndex, 150, -1, LVCF_WIDTH | LVCF_TEXT);
                ++nIndex;

                strTemp.Load(IDS_UDP_EXTERNAL);
                pListView->AddColumn(*strTemp, nIndex, 150, -1, LVCF_WIDTH | LVCF_TEXT);
                ++nIndex;

                strTemp.Load(IDS_UDP_TO_AUTHOR);
                pListView->AddColumn(*strTemp, nIndex, 150, -1, LVCF_WIDTH | LVCF_TEXT);
            }
            break;
        case (PAKT_SERVICE + PAKT_MAX):
            {
                strTemp.Load(IDS_ROUTINE_ID);
                pListView->AddColumn(*strTemp, nIndex, 320, -1, LVCF_WIDTH | LVCF_TEXT);
                ++nIndex;

                strTemp.Load(IDS_ROUTINE_ID_HASH);
                pListView->AddColumn(*strTemp, nIndex, 160, -1, LVCF_WIDTH | LVCF_TEXT);
                ++nIndex;

                strTemp.Load(IDS_ROUTINE_ID_LINK);
                pListView->AddColumn(*strTemp, nIndex, 160, -1, LVCF_WIDTH | LVCF_TEXT);
            }
            break;
        case (PAKT_GATE + PAKT_MAX):
            {
                strTemp.Load(IDS_ROUTINE_ID_HASH);
                pListView->AddColumn(*strTemp, nIndex, 160, -1, LVCF_WIDTH | LVCF_TEXT);
                ++nIndex;

                strTemp.Load(IDS_ROUTINE_ID_LINK);
                pListView->AddColumn(*strTemp, nIndex, 160, -1, LVCF_WIDTH | LVCF_TEXT);
                ++nIndex;

                strTemp.Load(IDS_ROUTINE_ID_REQ);
                pListView->AddColumn(*strTemp, nIndex, 200, -1, LVCF_WIDTH | LVCF_TEXT);
                ++nIndex;

                strTemp.Load(IDS_ROUTINE_ID_ACK);
                pListView->AddColumn(*strTemp, nIndex, 200, -1, LVCF_WIDTH | LVCF_TEXT);
            }
            break;
        default:
            {
                //assert(0);
            }
        }
    }
}

Int CCommonDlg::InitServerCommonData(Int nServerIndex)
{
    CXListView* pListView = GetListView(nServerIndex);
    assert(pListView != nullptr);

    Int nIndex = 0;
    CStringFix strTemp;
    strTemp.Load(nServerIndex + IDS_ID_BASE);
    pListView->AddColumn(*strTemp, nIndex, 80, -1, LVCF_WIDTH | LVCF_TEXT);
    ++nIndex;

    switch (nServerIndex)
    {
    case PAKT_BALANCE:
        {
            strTemp.Load(IDS_AUTHOR_COUNT);
            pListView->AddColumn(*strTemp, nIndex, 90, -1, LVCF_WIDTH | LVCF_TEXT);
            ++nIndex;

            strTemp.Load(IDS_EXTERNAL_COUNT);
            pListView->AddColumn(*strTemp, nIndex, 90, -1, LVCF_WIDTH | LVCF_TEXT);
            ++nIndex;
        }
        break;
    case PAKT_AUTHORDB:
    case PAKT_MASTERDB:
        {
            strTemp.Load(IDS_SERVER_COUNT);
            pListView->AddColumn(*strTemp, nIndex, 90, -1, LVCF_WIDTH | LVCF_TEXT);
            ++nIndex;

            strTemp.Load(IDS_DATA_COUNT);
            pListView->AddColumn(*strTemp, nIndex, 90, -1, LVCF_WIDTH | LVCF_TEXT);
            ++nIndex;
        }
        break;
    case PAKT_AUTHOR:
    case PAKT_MASTER:
    case PAKT_SERVICE:
    case PAKT_GATE:
        {
            strTemp.Load(IDS_ALL_COUNT);
            pListView->AddColumn(*strTemp, nIndex, 90, -1, LVCF_WIDTH | LVCF_TEXT);
            ++nIndex;

            strTemp.Load(IDS_ONLINE_COUNT);
            pListView->AddColumn(*strTemp, nIndex, 90, -1, LVCF_WIDTH | LVCF_TEXT);
            ++nIndex;
        }
        break;
    default:
        {
            //assert(0);
        }
    }
    strTemp.Load(IDS_LOAD_STATUS);
    pListView->AddColumn(*strTemp, nIndex, 80, -1, LVCF_WIDTH | LVCF_TEXT);
    ++nIndex;
    return nIndex;
}

bool CCommonDlg::AddServerData(Int nServerIndex, uintptr_t utData)
{
    CXListView* pListView = GetListView(nServerIndex);
    if (pListView != nullptr)
    {
        assert(utData != 0);
        SVR_COMMON_MAP::PSVR_PAIR pPair = reinterpret_cast<SVR_COMMON_MAP::PSVR_PAIR>(utData);
        assert(pPair->Value.usStatus & STATUSU_LINK);
#ifdef _DEBUG
        LVFINDINFO find = {0};
        find.flags = LVFI_PARAM;
        find.lParam = (LPARAM)(pPair->ullKey);
        assert(pListView->FindItem(&find) == -1);
#endif
        CStringFix strTemp;
        strTemp.ToString((ULong)pPair->Value.usId);
        Int nIndex = pListView->GetItemCount();
        nIndex = pListView->InsertItem(nIndex, *strTemp);
        if (nIndex >= 0)
        {
            strTemp.ToString((ULong)pPair->Value.uTotal);
            pListView->SetItemText(nIndex, 1, *strTemp);

            strTemp.ToString((ULong)pPair->Value.uOnline);
            pListView->SetItemText(nIndex, 2, *strTemp);

            if (pPair->Value.usLoad <= DATAD_OVER_LOAD)
            {
                strTemp.ToString((ULong)(pPair->Value.usLoad / DATAD_TOPERCENT));
            }
            else if (pPair->Value.usLoad < DATAD_MAY_DAY)
            {
                strTemp.Load(IDS_LOAD_WARN);
            }
            else
            {
                strTemp.Load(IDS_LOAD_MAYDAY);
            }
            pListView->SetItemText(nIndex, 3, *strTemp);

            AddServerDataAddr(nServerIndex, nIndex, pPair->Value.NetAddr);

            pListView->SetItemData(nIndex, (uintptr_t)pPair->ullKey);
            return true;
        }
        DEV_WARN(TF("Dlg界面增加%d索引服务器信息失败!"), nServerIndex);
    }
    return false;
}

bool CCommonDlg::UpdateServerData(Int nServerIndex, uintptr_t utData)
{
    CXListView* pListView = GetListView(nServerIndex);
    if (pListView != nullptr)
    {
        assert(utData != 0);
        SVR_COMMON_MAP::PSVR_PAIR pPair = reinterpret_cast<SVR_COMMON_MAP::PSVR_PAIR>(utData);
        assert(pPair->Value.usStatus & (STATUSU_SYNC | STATUSU_LINK));
        LVFINDINFO find = {0};
        find.flags = LVFI_PARAM;
        find.lParam = (LPARAM)(pPair->ullKey);
        Int nIndex = pListView->FindItem(&find);
        if (nIndex > -1)
        {
            CStringFix strTemp;
            strTemp.ToString((ULong)pPair->Value.uTotal);
            pListView->SetItemText(nIndex, 1, *strTemp);

            strTemp.ToString((ULong)pPair->Value.uOnline);
            pListView->SetItemText(nIndex, 2, *strTemp);

            if (pPair->Value.usLoad <= DATAD_OVER_LOAD)
            {
                strTemp.ToString((ULong)(pPair->Value.usLoad / DATAD_TOPERCENT));
            }
            else if (pPair->Value.usLoad < DATAD_MAY_DAY)
            {
                strTemp.Load(IDS_LOAD_WARN);
            }
            else
            {
                strTemp.Load(IDS_LOAD_MAYDAY);
            }
            pListView->SetItemText(nIndex, 3, *strTemp);
            return true;
        }
        DEV_WARN(TF("Dlg界面更新%d索引服务器信息失败!"), nServerIndex);
    }
    return false;
}

bool CCommonDlg::RemoveServerData(Int nServerIndex, uintptr_t utData)
{
    CXListView* pListView = GetListView(nServerIndex);
    if (pListView != nullptr)
    {
        if (utData != 0)
        {
            LVFINDINFO find = {0};
            find.flags = LVFI_PARAM;
            find.lParam = (LPARAM)(utData);
            Int nIndex = pListView->FindItem(&find);
            if (nIndex > -1)
            {
                pListView->DeleteItem(nIndex);
            }
            else
            {
                DEV_WARN(TF("Dlg界面删除%d索引服务器信息失败!"), nServerIndex);
            }
        }
        else
        {
            pListView->DeleteAllItems();
        }
    }
    return true;
}

void CCommonDlg::AddServerDataAddr(Int nServerIndex, Int nIndex, void* pAddr)
{
    CXListView* pListView = GetListView(nServerIndex);
    assert(pListView != nullptr);

    CNetAddr* pNetAddr = reinterpret_cast<CNetAddr*>(pAddr);

    CStringFix strTemp;

    CStrAddr strAddr;

    switch (nServerIndex)
    {
    case PAKT_BALANCE:
        {
            // udp
            GServerLoaderInst->m_NetworkPtr->TranslateAddr(strAddr.strIp, strAddr.usPort, *pNetAddr, false);
            strTemp.Format(TF("[%s]:%d"), *strAddr.strIp, strAddr.usPort);
            pListView->SetItemText(nIndex, 4, *strTemp);
        }
        break;
    case PAKT_AUTHORDB:
        {
            GServerLoaderInst->m_NetworkPtr->TranslateAddr(strAddr.strIp, strAddr.usPort, *pNetAddr, false);
            strTemp.Format(TF("[%s]:%d"), *strAddr.strIp, strAddr.usPort);
            pListView->SetItemText(nIndex, 4, *strTemp);
        }
        break;
    case PAKT_AUTHOR:
        {
            // tcp
            GServerLoaderInst->m_NetworkPtr->TranslateAddr(strAddr.strIp, strAddr.usPort, *pNetAddr, false);
            strTemp.Format(TF("[%s]:%d"), *strAddr.strIp, strAddr.usPort);
            pListView->SetItemText(nIndex, 4, *strTemp);
            // udp
            ++pNetAddr;
            GServerLoaderInst->m_NetworkPtr->TranslateAddr(strAddr.strIp, strAddr.usPort, *pNetAddr, false);
            strTemp.Format(TF("[%s]:%d"), *strAddr.strIp, strAddr.usPort);
            pListView->SetItemText(nIndex, 5, *strTemp);
            // authordb
            ++pNetAddr;
            if (pNetAddr->usPort != 0)
            {
                GServerLoaderInst->m_NetworkPtr->TranslateAddr(strAddr.strIp, strAddr.usPort, *pNetAddr, false);
                strTemp.Format(TF("[%s]:%d"), *strAddr.strIp, strAddr.usPort);
            }
            else
            {
                strTemp.Load(IDS_NONE_MARK);
            }
            pListView->SetItemText(nIndex, 6, *strTemp);
        }
        break;
    case PAKT_MASTERDB:
        {
            GServerLoaderInst->m_NetworkPtr->TranslateAddr(strAddr.strIp, strAddr.usPort, *pNetAddr, false);
            strTemp.Format(TF("[%s]:%d"), *strAddr.strIp, strAddr.usPort);
            pListView->SetItemText(nIndex, 4, *strTemp);
        }
        break;
    case PAKT_MASTER:
        {
            GServerLoaderInst->m_NetworkPtr->TranslateAddr(strAddr.strIp, strAddr.usPort, *pNetAddr, false);
            strTemp.Format(TF("[%s]:%d"), *strAddr.strIp, strAddr.usPort);
            pListView->SetItemText(nIndex, 4, *strTemp);
            // udp
            ++pNetAddr;
            GServerLoaderInst->m_NetworkPtr->TranslateAddr(strAddr.strIp, strAddr.usPort, *pNetAddr, false);
            strTemp.Format(TF("[%s]:%d"), *strAddr.strIp, strAddr.usPort);
            pListView->SetItemText(nIndex, 5, *strTemp);
            // masterdb
            ++pNetAddr;
            if (pNetAddr->usPort != 0)
            {
                GServerLoaderInst->m_NetworkPtr->TranslateAddr(strAddr.strIp, strAddr.usPort, *pNetAddr, false);
                strTemp.Format(TF("[%s]:%d"), *strAddr.strIp, strAddr.usPort);
            }
            else
            {
                strTemp.Load(IDS_NONE_MARK);
            }
            pListView->SetItemText(nIndex, 6, *strTemp);
        }
        break;
    case PAKT_SERVICE:
        {
            // master
            GServerLoaderInst->m_NetworkPtr->TranslateAddr(strAddr.strIp, strAddr.usPort, *pNetAddr, false);
            strTemp.Format(TF("[%s]:%d"), *strAddr.strIp, strAddr.usPort);
            pListView->SetItemText(nIndex, 4, *strTemp);
            // masterdb
            ++pNetAddr;
            if (pNetAddr->usPort != 0)
            {
                GServerLoaderInst->m_NetworkPtr->TranslateAddr(strAddr.strIp, strAddr.usPort, *pNetAddr, false);
                strTemp.Format(TF("[%s]:%d"), *strAddr.strIp, strAddr.usPort);
            }
            else
            {
                strTemp.Load(IDS_NONE_MARK);
            }
            pListView->SetItemText(nIndex, 5, *strTemp);
        }
        break;
    case PAKT_GATE:
        {
            // tcp
            GServerLoaderInst->m_NetworkPtr->TranslateAddr(strAddr.strIp, strAddr.usPort, *pNetAddr, false);
            strTemp.Format(TF("[%s]:%d"), *strAddr.strIp, strAddr.usPort);
            pListView->SetItemText(nIndex, 4, *strTemp);
            pListView->SetItemText(nIndex, 5, *strTemp);
            // udp
            ++pNetAddr;
            GServerLoaderInst->m_NetworkPtr->TranslateAddr(strAddr.strIp, strAddr.usPort, *pNetAddr, false);
            strTemp.Format(TF("[%s]:%d"), *strAddr.strIp, strAddr.usPort);
            pListView->SetItemText(nIndex, 6, *strTemp);
        }
        break;
    default:
        {
        }
    }
}

